﻿using Microsoft.Hadoop.Client;
using Microsoft.Hadoop.MapReduce;
using Microsoft.Hadoop.WebClient.WebHCatClient;
using Microsoft.Hadoop.WebHDFS;
using Microsoft.Hadoop.WebHDFS.Adapters;
using Microsoft.Win32;
using Microsoft.WindowsAzure.Management.HDInsight;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewMaker;
using ViewMaker.Core;
using ViewMaker.Core.Controls;
namespace HDInsightStudio
{

    [View(typeof(JarMapReduceStudioView))]
    [ViewProperty(ViewControl.Properties.WindowHeight, 400)]
    [ViewProperty(ViewControl.Properties.WindowWidth, 600)]
    public class JarMapReduceStudio : JobViewModelBase
    {

        public string JarFile
        {
            get { return _JarFile; }
            set { _JarFile = value; OnPropertyChanged("JarFile"); }
        }
        private string _JarFile;

        public string ClassName
        {
            get { return _ClassName; }
            set { _ClassName = value; OnPropertyChanged("ClassName"); }
        }
        private string _ClassName;

        public string Arguments
        {
            get { return _Arguments; }
            set { _Arguments = value; OnPropertyChanged("Arguments"); }
        }
        private string _Arguments;

        public string Defines
        {
            get { return _Defines; }
            set { _Defines = value; OnPropertyChanged("Defines"); }
        }
        private string _Defines;


        public bool Busy
        {
            get { return _busy; }
            set { _busy = value; OnPropertyChanged(null); }
        }
        private bool _busy;

        public string StdErr
        {
            get { return _StdErr; }
            set { _StdErr = value; OnPropertyChanged("StdErr"); }
        }
        private string _StdErr;

        private string HomeFolder = "/JarMapReduceStudio";
        public JarMapReduceStudio()
            : this(DateTime.Now.ToString("yyyyMMddHHmmss"))
        {
        }

        public JarMapReduceStudio(string jobId)
            : base(jobId)
        {
            Status = HomeFolder + "/" + jobId + "/Status/";

        }


        public ICommand ExecuteMapReduceCommand
        {
            get { return this.CreateCommand(ExecuteMapReduce, (x) => !Busy); }
        }
        private void ExecuteMapReduce()
        {
            StdErr = "";
            if (!string.IsNullOrEmpty(JarFile) && !string.IsNullOrEmpty(ClassName))
            {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += (s, e) =>
                {
                    Busy = true;


                    var jobDefintion = new MapReduceJobCreateParameters()
                    {
                        JobName = "MapReduce Studio",
                        StatusFolder = Status,
                        JarFile = JarFile,
                        ClassName = ClassName,
                    };

                    if (!string.IsNullOrEmpty(Arguments))
                    {
                        foreach (var item in Arguments.Split('\n'))
                        {
                            if (!string.IsNullOrEmpty(item)) jobDefintion.Arguments.Add(item);
                        }
                    }
                    if (!string.IsNullOrEmpty(Defines))
                    {
                        foreach (var item in Defines.Split('\n'))
                        {
                            var data = item.Split('=');
                            if (!string.IsNullOrEmpty(item)) jobDefintion.Defines.Add(data[0].Trim(),data.Length > 1 ? string.Join("=",data.Skip(1)) : "");
                        }
                    }

                    var jobResult = Config.JobClient.CreateMapReduceJob(jobDefintion);

                    WaitForJobCompletion(jobResult, ProgressProc);
                    StdErr = ReadError();
                    Busy = false;

                };
                worker.RunWorkerAsync();


            }
        }
        private bool ProgressProc(JobDetails job)
        {
            StdErr = ReadError();
            return true;
        }

        protected override void Save()
        {
            JObject data = new JObject{
                { "Type", this.GetType().Name },
                { "JarFile", JarFile },
                { "ClassName", ClassName },
                { "Arguments", Arguments },
                { "Defines", Defines },
            };
            SaveData(data);
        }

        protected override void Load()
        {
            var data = LoadData();
            if (data == null) return;
            if ((string)data.Property("Type").Value != this.GetType().Name)
            {
                this.ShowMessage("Invalid selected file. " + data.Property("Type").Value);
            }
            else
            {
                this.JarFile = (string)data.Property("JarFile").Value;
                this.ClassName = (string)data.Property("ClassName").Value;
                this.Arguments = (string)data.Property("Arguments").Value;
                this.Defines = (string)data.Property("Defines").Value;
            }
        }

    }
}
